package com.zenchn.utils;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import org.springframework.util.FileCopyUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Zxing  二维码编码解码工具类
 * @author  dingxinfa
 * @date 2019-09-30
 */
public class ZxingQRCodeUtils {

    /**
     * 生成二维码图片
     *
     * @param width
     * @param height
     * @param content     二维码中的数据
     * @param fileName    文件名
     * @param imageFormat 图像格式
     * @param logoFile    logo文件
     * @throws WriterException
     * @throws IOException
     */
    public static File encoderQRCode(Integer width, Integer height, String content, String fileName, String imageFormat, File logoFile) throws WriterException, IOException {


        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(16);
        /*
        *  排错率  L<M<Q<H ;不设置 自动适应
        *  hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        */

        //编码
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //外边距：margin
        hints.put(EncodeHintType.MARGIN, 1);

        /*
         * content : 需要加密的 文字
         * BarcodeFormat.QR_CODE:要解析的类型（二维码）
         * width：宽度
         * height：高度
         * hints：加密涉及的一些参数：编码、排错率
         */
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);

        //内存中的一张图片：此时需要的图片 是二维码-> 需要一个boolean[][] ->BitMatrix
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, (bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB()));
            }
        }

        //画logo
        image = logoMatrix(image, logoFile);

        File qrCodeFile = File.createTempFile(fileName.toString(), "." + imageFormat);
        //生成图片
        ImageIO.write(image, imageFormat, qrCodeFile);

        return qrCodeFile;
    }


    /***
     * 传入logo、二维码 ->带logo的二维码
     * @param matrixImage  二维码缓存图像
     * @param logoFile   logo 文件
     * @return
     * @throws IOException
     */
    public static BufferedImage logoMatrix(BufferedImage matrixImage, File logoFile) throws IOException {

        //画logo： String->BufferedImage(内存)
        BufferedImage logoImg = ImageIO.read(logoFile);
        int height = matrixImage.getHeight();
        int width = matrixImage.getWidth();


        //在二维码上画logo:产生一个  二维码画板
        Graphics2D g2 = matrixImage.createGraphics();
        //纯logo图片
        g2.drawImage(logoImg, width * 2 / 5, height * 2 / 5, width * 1 / 5, height * 1 / 5, null);

        //产生一个 画 白色圆角正方形的 画笔
        BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        //将画板-画笔 关联
        g2.setStroke(stroke);
        //创建一个正方形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(width * 2 / 5, height * 2 / 5, width * 1 / 5, height * 1 / 5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        g2.setColor(Color.WHITE);
        g2.draw(round);

        //灰色边框
        BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        g2.setStroke(stroke2);
        //创建一个正方形
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(width * 2 / 5 + 2, height * 2 / 5 + 2, width * 1 / 5 - 4, height * 1 / 5 - 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        // Color color = new Color(128,128,128) ;
        g2.setColor(Color.GRAY);
        g2.draw(round2);

        g2.dispose();
        matrixImage.flush();

        return matrixImage;
    }


    /**
     * 解析二维码
     *
     * @param file 二维码图片文件
     */
    public static String decoderQRCode(File file) throws Exception {
        BufferedImage image = ImageIO.read(file);
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        Binarizer binarizer = new HybridBinarizer(source);
        BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
        Map<DecodeHintType, Object> hintType = new HashMap<DecodeHintType, Object>(16);
        hintType.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        // 对图像进行解码
        Result result = new MultiFormatReader().decode(binaryBitmap, hintType);
        return result.getText();
    }


    public static void main(String[] args) {
        //内容信息
        //String content = "https://zdzcbuilding.oss-cn-hangzhou.aliyuncs.com/formal/apk/1C709996A5494A04907DDF1857D33580/city_houses_assistant_v1.0.2.apk";

        String content ="再过两天，今年的云栖大会将要开幕。对于今天的杭州而言，云栖大会是一张响当当的数字经济名片，它的影响力已经超出了这座城市本身的范畴，而成为大数据、云计算和人工智能产业的风向标。\n" +
                "从电商、物流、再到AI、云计算、金融科技、区块链，今天的杭州引领着许多创新产业的趋势。在人们的心目中，她早已不仅仅是一个拥有秀美西湖的旅游城市，而蝶变为具有全国影响力的新经济高地。\n" +
                "越来越多的人会自然而然地提起“北上广深杭”的概念，虽然杭州的经济总量在全国城市中并不算突出。2011年以前，杭州的GDP曾长期在全国城市中排名第八，在省会城市中仅次于广州。2012年，杭州以9%的经济增速落后于成都的13%和武汉的12%，从而在经济总量上被后两者赶超，此后一直保持在全国第十的位置上。\n" +
                "但是杭州的实际影响力排位，明显超过她的GDP排位。这是今天中国经济变革的一个独特样本。";

        String fileName="文本测试";
        String imageFormat="jpg";
        String saveFile="D://"+fileName+"."+imageFormat;
        int size=400;
        try {
            File qrCodeFile=encoderQRCode(size, size, content, fileName, imageFormat, new File("D://mao.jpg"));
            FileCopyUtils.copy(qrCodeFile, new File(saveFile));

            System.out.println(decoderQRCode(new File(saveFile)));

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
